﻿#include <Sys\RenderUnit\SysRenderDatagram\LIGHTATTRIBRD.HPP>
#include <Render\Render_Win32\Render_Win32_D3D\RENDER_WIN32_D3D9.HPP>
#include <Sys\RenderUnit\SYSDDCLASSID.HPP>

using namespace CxxlMan;
using namespace Cxxl3D;

class CLightAttribDD_D3D9:public IDatagramDisposal_D3d9, public ILightAttribBridge
{
  class CLightAttrib_CEO:public ILightAttrib_CEO
  { 
    LPDIRECT3DDEVICE9 m_pDEVICE9;
    // bool m_Light; // 燈光功能
    D3DMATERIAL9 mtrl;

    // 燈光功能 true = ON  false = OFF 
    virtual void cxxlFASTCALL Light(bool Switch)
    {
      m_pDEVICE9->SetRenderState(D3DRS_LIGHTING, Switch);
      //m_Light = Switch;
      if(Switch)
      {
        m_pDEVICE9->SetRenderState(D3DRS_COLORVERTEX, FALSE);
        m_pDEVICE9->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
        m_pDEVICE9->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
        m_pDEVICE9->SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL);
      }
      else
      {
        m_pDEVICE9->SetRenderState(D3DRS_COLORVERTEX, TRUE);
        m_pDEVICE9->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1);
        m_pDEVICE9->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
        m_pDEVICE9->SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR1);
      }
    }

    // 反光功能 true = ON  false = OFF 
    virtual void cxxlFASTCALL Specular(bool Switch)
    {
      m_pDEVICE9->SetRenderState(D3DRS_SPECULARENABLE,Switch);
    }

    // Switch = true:計算每個頂點到鏡頭的向量 false:假設頂點就在鏡頭前方，加快速度
    virtual void cxxlFASTCALL Specular_LocalViewer(bool Switch)
    {
      m_pDEVICE9->SetRenderState(D3DRS_LOCALVIEWER, Switch);
    }

    // 是否為 Normalize 做正規化處理
    // Switch = true:是  false:否
    /*
    virtual void cxxlFASTCALL AutoNormalize(bool Switch)
    {
      m_pDEVICE9->SetRenderState(D3DRS_NORMALIZENORMALS, Switch);

      // 經由呼叫SetMaterial來設定材質
      m_pDEVICE9->SetMaterial(&mtrl);
    }
    */


    // 設定顏色
    virtual void cxxlFASTCALL SetColor(C3D_FLOAT *Color)
    {
      //if(m_Light)
      //{
        mtrl.Specular.r = mtrl.Diffuse.r = mtrl.Ambient.r = Color[0];
        mtrl.Specular.g = mtrl.Diffuse.g = mtrl.Ambient.g = Color[1];
        mtrl.Specular.b = mtrl.Diffuse.b = mtrl.Ambient.b = Color[2];
        mtrl.Specular.a = mtrl.Diffuse.a = mtrl.Ambient.a = Color[3];

	      // 經由呼叫SetMaterial來設定材質
	      m_pDEVICE9->SetMaterial(&mtrl);
      //}
    }

    // 設定 Emissive 顏色
    virtual void cxxlFASTCALL SetEmissive(C3D_FLOAT *EmissiveColor)
    {
      mtrl.Emissive.r = EmissiveColor[0];
      mtrl.Emissive.g = EmissiveColor[1];
      mtrl.Emissive.b = EmissiveColor[2];
      mtrl.Emissive.a = EmissiveColor[3];

      // 經由呼叫SetMaterial來設定材質
      m_pDEVICE9->SetMaterial(&mtrl);
    }

    // 設定材質反光銳利度
    virtual void cxxlFASTCALL SetMaterialShininess(C3D_FLOAT MaterialShininess)
    {
      mtrl.Power = MaterialShininess;

      // 經由呼叫SetMaterial來設定材質
      m_pDEVICE9->SetMaterial(&mtrl);
    }

  public:
    CLightAttrib_CEO()
    {
      //m_Light = false;
      ZeroMemory( &mtrl, sizeof(mtrl) );
    }
    virtual ~CLightAttrib_CEO(){}

    void cxxlFASTCALL SetDEVICE9(LPDIRECT3DDEVICE9 pDEVICE9)
    {
      m_pDEVICE9 = pDEVICE9;
    }
  }Attrib_CEO;



  virtual bool cxxlFASTCALL Exec(const Smart_Ptr<IRenderDatagramDisposalCenterD3d> &IRenderDatagramDisposalCenterD3d_Arg,
    const Smart_Ptr<IRenderDatagram> &IRenderDatagram_Arg, LPDIRECT3DDEVICE9 pDEVICE9)
  {
    if(actILightAttribRD_Ptr.isNULL())
    {
      if(IRenderDatagram_Arg.isNULL() == false)
      {
        actILightAttribRD_Ptr = (ILightAttribRD*)GetDefaultInterface(IRenderDatagram_Arg);
        Attrib_CEO.SetDEVICE9(pDEVICE9);
        isModified(actILightAttribRD_Ptr);
        SetAll(actILightAttribRD_Ptr, &Attrib_CEO);
      }
    }
    else if(isModified(actILightAttribRD_Ptr))
    {
      if(IRenderDatagram_Arg.isNULL() == false)
        actILightAttribRD_Ptr = (ILightAttribRD*)GetDefaultInterface(IRenderDatagram_Arg);

      Attrib_CEO.SetDEVICE9(pDEVICE9);
      SetAll(actILightAttribRD_Ptr, &Attrib_CEO);
    }
    else if(IRenderDatagram_Arg.isNULL() == false)
    {
      Smart_Ptr<ILightAttribRD> ILightAttribRD_Ptr = (ILightAttribRD*)GetDefaultInterface(IRenderDatagram_Arg);
      if((ILightAttribRD*)actILightAttribRD_Ptr != (ILightAttribRD*)ILightAttribRD_Ptr)
      {
        Attrib_CEO.SetDEVICE9(pDEVICE9);
        Chk(actILightAttribRD_Ptr, ILightAttribRD_Ptr, &Attrib_CEO);
        actILightAttribRD_Ptr = ILightAttribRD_Ptr;
      }
    }

    return true;
  }

  Smart_Ptr<ILightAttribRD> actILightAttribRD_Ptr;

public:
  // Consteructor
  CLightAttribDD_D3D9()
    :cxxlObject(Spirit_Easy),
    actILightAttribRD_Ptr(NULL,this)
  {
  }

  // Desteructor
  virtual ~CLightAttribDD_D3D9()
  {
  }

};


cxxlObject *cxxlFASTCALL New_CLightAttribDD_D3D9()
{
  return new CLightAttribDD_D3D9;
}